<script lang="jsx">
import { defineComponent, nextTick, ref, watch } from 'vue'
import { debounce, template } from 'lodash-es'
import { doApi, getFormValues } from '@/api/basic'
import { doSelectChange } from '../AutoGrid/tool.ts'

export default defineComponent({
  name: 'PageSelect',
  props: {
    modelValue: {
      type: [String, Number, Array],
      default: ''
    },
    col: {
      type: Object,
      default: () => ({})
    },
    grid: {
      type: Object,
      default: () => ({})
    },
    form: {
      type: Object,
      default: () => ({})
    }
  },
  emits: ['update:modelValue', 'enter', 'search'],
  setup(props, { emit, attrs }) {
    const selectRef = ref()
    const col = props.col
    const grid = props.grid
    const form = props.form
    const isLoading = ref(false)
    const list = ref(col.values || [])
    // 首次加载
    const enumRemoteMethod = (qs) => {
      if (isLoading.value) {
        return
      }
      console.log('xxx')
      if (col.source) {
        // 如果配置了full_data，只查询一次后，就不再查询了
        if (col.source?.full_data && col._fullData) {
          col._qs = qs
          return
        }
        const sourceObj = {
          ...(typeof col.source === 'string' ? { source: col.source } : col.source),
          ...(grid?.source &&
            (typeof grid.source === 'string' ? { source: grid.source } : grid.source))
        }
        const source = sourceObj.source
        const conditions = {}
        Object.keys(sourceObj.conditions || {}).forEach((key) => {
          try {
            const value = template(sourceObj.conditions[key])(form || {})
            if (!value.includes('${')) {
              conditions[key] = value
            }
          } catch (e) {
            // conditions[key] = sourceObj.conditions[key];
          }
        })
        if (qs) {
          const field = sourceObj.nameField || source.split('.').reverse()[0]
          conditions[field] = qs
        }
        if (!col._query) {
          col._query = { page: 1, size: 20, qs }
        }
        // 如果上一次的查询条件相同，不再重新查询
        if (col._query?.conditions === JSON.stringify(conditions)) {
          return
        } else {
          col._query.page = 1
        }
        col._query.conditions = JSON.stringify(conditions)
        isLoading.value = true
        if (sourceObj.url) {
          doApi(
            sourceObj.url,
            {
              ...sourceObj,
              page: col._query.page,
              size: col._query.size,
              conditions,
              url: undefined,
              keyField: undefined,
              nameField: undefined,
              showFields: undefined,
              showHeaders: undefined
            },
            sourceObj.method
          )
            .then((res) => {
              if (col._query) {
                col._query.count = res.count
              }
              const result = res.data || []
              isLoading.value = undefined
              list.value = result
              if (col.source?.full_data) {
                col._fullData = true
              }
            })
            .finally(() => {
              isLoading.value = false
            })
        } else {
          getFormValues({
            ...sourceObj,
            conditions,
            page: 1,
            size: 20,
            keyField: undefined,
            nameField: undefined,
            showFields: undefined,
            showHeaders: undefined
          })
            .then((res) => {
              if (col._query) {
                col._query.count = res.count
              }
              const result = res.values || []
              isLoading.value = undefined
              list.value = result
              if (col.source?.full_data) {
                col._fullData = true
              }
            })
            .finally(() => {
              isLoading.value = false
            })
        }
      }
    }

    // 分页加载更多
    const loadMoreMethod = (col) => {
      if (isLoading.value) {
        return
      }
      if (col.source) {
        if (!col?._query?.count || col?._query?.page * col?._query?.size >= col?._query?.count) {
          return
        }
        isLoading.value = true
        const sourceObj = {
          ...(typeof col.source === 'string' ? { source: col.source } : col.source),
          ...(grid?.source &&
            (typeof grid.source === 'string' ? { source: grid.source } : grid.source))
        }

        const source = sourceObj.source
        const conditions = {}
        Object.keys(sourceObj.conditions || {}).forEach((key) => {
          try {
            const value = template(sourceObj.conditions[key])(form || {})
            if (!value.includes('${')) {
              conditions[key] = value
            }
          } catch (e) {
            conditions[key] = sourceObj.conditions[key]
          }
        })
        const query = col._query
        if (query?.qs) {
          const field = sourceObj.nameField || source.split('.').reverse()[0]
          conditions[field] = query?.qs
        }
        if (sourceObj.url) {
          doApi(
            sourceObj.url,
            { ...sourceObj, page: ++query.page, size: col._query.size, conditions },
            sourceObj.method
          )
            .then((res) => {
              if (col._query) {
                col._query.count = res.count
              }
              const result = res.data || []
              isLoading.value = undefined
              list.value.push(...result)
            })
            .finally(() => {
              isLoading.value = false
            })
        } else {
          getFormValues({
            ...sourceObj,
            conditions,
            page: ++query.page,
            size: 20,
            keyField: undefined,
            nameField: undefined,
            showFields: undefined,
            showHeaders: undefined
          })
            .then((res) => {
              query.pageCount = res.count
              const result = res.values || []
              isLoading.value = undefined
              list.value.push(...result)
            })
            .finally(() => {
              isLoading.value = false
            })
        }
      }
    }

    // 回显数据
    const loadOneMethod = (col) => {
      if (isLoading.value) {
        return
      }
      if (col.source) {
        isLoading.value = true
        const sourceObj = {
          ...(typeof col.source === 'string' ? { source: col.source } : col.source),
          ...(grid?.source &&
            (typeof grid.source === 'string' ? { source: grid.source } : grid.source))
        }
        // const source = sourceObj.source
        const conditions = {}
        if (sourceObj.keyField && !['list', 'tree-select-multiple'].includes(col.type)) {
          conditions[sourceObj.keyField] = form[col.key]
        } else {
          conditions.ids = [form[col.key]].flat()
        }
        const query = col._query
        getFormValues({
          ...sourceObj,
          conditions,
          ...query,
          keyField: undefined,
          nameField: undefined,
          showFields: undefined,
          showHeaders: undefined
        })
          .then((res) => {
            const result = res.values || []
            isLoading.value = undefined
            list.value = result
          })
          .finally(() => {
            isLoading.value = false
          })
      }
    }

    // 只要加载过数据dataLoaded
    const dataLoaded = ref(false)
    watch(isLoading, (val) => {
      if (val && !dataLoaded.value) {
        dataLoaded.value = true
      }
    })
    watch(
      () => props.modelValue,
      (val) => {
        if ((val === 0 || val || (val && Object.keys(val)?.length)) && !dataLoaded.value) {
          // 列表页已经查询了所有下拉数据，暂时去掉
          loadOneMethod(col)
        }
      },
      { immediate: true }
    )

    const debounceLoad = debounce(function () {
      loadMoreMethod(col)
    }, 200)
    // 滚动事件
    const handleScroll = (e) => {
      const dropdown = e.target
      const scrollTop = dropdown.scrollTop
      const scrollHeight = dropdown.scrollHeight
      const clientHeight = dropdown.clientHeight
      const isBottom = scrollTop + clientHeight >= scrollHeight - 10
      if (isBottom) {
        debounceLoad()
      }
    }

    return () => (
      <el-select
        filterable
        clearable
        teleported={true}
        placeholder="请选择"
        popper-class="page-select-popper"
        {...attrs}
        ref={selectRef}
        {...(col.source
          ? {
              remote: true,
              'remote-show-suffix': true,
              'remote-method': enumRemoteMethod
            }
          : {})}
        modelValue={
          col.source?.number && props.modelValue ? Number(props.modelValue) : props.modelValue
        } // 将字符串转换为数字以匹配选项
        onUpdate:modelValue={(val) => {
          // 手动处理数据转换
          emit('update:modelValue', col.source?.number ? String(val) : val)
        }}
        onClear={() => {
          // 点击clear事件，clear恢复默认值
          emit('update:modelValue', '')
        }}
        onVisibleChange={(val) => {
          // 下拉框出现/隐藏时，添加/删除滚动事件
          nextTick(() => {
            const el = selectRef.value?.popperRef
            const dropdown = el?.querySelector('.el-select-dropdown .el-select-dropdown__wrap')
            if (dropdown) {
              if (val) {
                dropdown.addEventListener('scroll', handleScroll)
              } else {
                dropdown.removeEventListener('scroll', handleScroll)
              }
            }
          })
        }}
        {...(col.watch || col?.source?.results
          ? {
              onChange: (val) => {
                doSelectChange(form, col, 'change', val)
              }
            }
          : {})}
        v-slots={
          col.source?.showHeaders?.length
            ? {
                header: () => (
                  <div
                    style={`display: grid; grid-template-columns: repeat(${
                      col.source?.showHeaders?.length || 1
                    }, 1fr); padding: 0 20px 0 10px`}
                  >
                    {(col.source?.showHeaders || []).map((item, i) => (
                      <div key={i} style={{ 'text-align': i > 0 ? 'right' : 'left' }}>
                        {item}
                      </div>
                    ))}
                  </div>
                )
              }
            : {}
        }
      >
        {(list.value || col.values)
          ?.filter((val) =>
            col.source?.full_data && col._qs
              ? `${val[col?.source?.nameField || 'name']}`.includes(col._qs)
              : true
          )
          ?.map((val) =>
            typeof val === 'object' ? (
              <el-option
                key={val[col?.source?.keyField || 'key']}
                label={val[col?.source?.nameField || 'name']}
                value={val[col?.source?.keyField || 'key']}
              >
                {col.source?.showFields ? (
                  <div
                    style={`display: grid; grid-template-columns: repeat(${
                      col.source?.showHeaders?.length >= col.source?.showFields?.length
                        ? col.source?.showHeaders?.length
                        : col.source?.showFields?.length + 1
                    }, 1fr)`}
                  >
                    {!col.source?.showHeaders?.length ||
                    col.source?.showFields?.length < col.source?.showHeaders?.length ? (
                      <span style="text-align: left">{val[col.source.nameField || 'name']}</span>
                    ) : undefined}
                    {col.source.showFields.map((field, i) => (
                      <span
                        key={field}
                        style={`${
                          col.source?.showFields?.length >= col.source?.showHeaders?.length && i < 1
                            ? 'text-align: left'
                            : 'text-align: right; margin-left: 10px'
                        }; color: var(--el-text-color-secondary); font-size: 13px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis`}
                      >
                        {val[field]}
                      </span>
                    ))}
                  </div>
                ) : undefined}
              </el-option>
            ) : (
              <el-option key={val} label={val} value={val} />
            )
          )}
      </el-select>
    )
  }
})
</script>
<style lang="less">
.page-select-popper {
  max-width: 480px;
}
</style>
